#################################################################
# Programa que efetua o filtro da Base de Dados					#
# 																#
# Autora: Cristina Teixeira de Oliveira							#
# e-mail: cto@icmc.usp.br										#
#################################################################
 
#################################################################
# Ao chamar a função, devem ser passados um arquivo de a ser	#
# filtrado 	e a Base de Dados									#
# Ex.: filtraBaseDados entrada baseDados 						#
# Onde, entrada irá conter o a estrutura secundaria do RNAnc a 	#
# ser procurado na base.										#
################################################################# 
 
#!usr/bin/perl -w
use strict;

my $descBase;
my $estruturaBase;
my $sequenciaBase;
my $qtdeSubcadeiasBase;
my @subcadeiaBase;
my $qtdePareadosBase;
my $qtdeNaoPareadosBase;
my $totalAninhadosBase;
my $tamFiltroSubcadeiaBase;
my @filtroSubcadeiaBase;

my $estruturaIn;
my $qtdeSubcadeiasIn;
my @subcadeiaIn;
my $qtdePareadosIn;
my $qtdeNaoPareadosIn;
my $totalAninhadosIn;
my $tamFiltroSubcadeiaIn;
my @filtroSubcadeiaIn;

my $i;
my $linha; 
my $homologo;
my $qtdeVotos;
my $qtdeForaLimite;
my $maxQtdeNivel;

#Definindo erro para corte de sequencias
my $erro = 0.01;
my $intervalo;
my $LIqtdeSubcadeias;
my $LSqtdeSubcadeias;
my $LIqtdePareados;
my $LSqtdePareados;	
my $LIqtdeNaoPareado;
my $LSqtdeNaoPareado;
my $LItotalAninhados;
my $LStotalAninhados;
my $LIfiltroSubcadeia;
my $LSfiltroSubcadeia;
my $minimoVotos = 4;
my $maxForaLimite = 4;		

# Exemplo de sequencias
# GTCCGCTCCGTCTATCAATACCGTTCGATTCGCTACCTTCGATGATTTTCGTACAGTCTG	........................((((..........))))..................	1	((((..........))))	4	42
# CCACTAGGAAGGCCTCAGTACGCCATGTCAGTTCTCCCCCGCGGATTTAGCTCAGTTGGG	..........(((........)))............(((.((.((......)).)).)))	2	(((........)))	(((.((.((......)).)).)))	10	22

sub extraiInformacao {	
	$linha = $_[0];
	#print "\nLinha: ", $linha;
	
	#Estrutura Secundaria
	$linha =~ s/(^[\.\(\)]*)//;
	#print "\nEstrutura Secundária: ", $1;
	$estruturaBase = $1;	
	$linha =~ s/(^\t)//;
	
	#Quantidade de Subcadeias
	$linha =~ s/(^[0-9]*)//;
	#print " Qtde Subcadeia: ", $1;
	$qtdeSubcadeiasBase = $1;
	$linha =~ s/(^\t)//;
	
	#Subcadeias		
	for ($i = 1;$i <= $qtdeSubcadeiasBase; $i=$i+1) {
    	$linha =~ s/(^[\.\(\)]*)//;
		#print " Subcadeia: ", $1;
		@subcadeiaBase[$i] = $1;
		
		$linha =~ s/(^\t)//;
	}
	
	#Quantidade de Pareamentos	
	$linha =~ s/(^[0-9]*)//;
	#print " Qtde Pareados: ", $1;
	$qtdePareadosBase = $1;
	$linha =~ s/(^\t)//;
	
	#Quantidade de Não-Pareados
	$linha =~ s/(^[0-9]*)//;
	#print " Qtde Não Pareado: ", $1;
	$qtdeNaoPareadosBase = $1;
	$linha =~ s/(^\t)//;
	
	#Quantidade de Não-Pareados
	$linha =~ s/(^[0-9]*)//;
	#print " Qtde Não Pareado: ", $1;
	$totalAninhadosBase = $1;
	$linha =~ s/(^\t)//;
	
	#Quantidade de Niveis
	$linha =~ s/(^[0-9]*)//;
	#print " Qtde Niveis: ", $1;
	$tamFiltroSubcadeiaBase = $1;
	$linha =~ s/(^\t)//;
	
	#Niveis
	for ($i = 1;$i <= $tamFiltroSubcadeiaBase; $i=$i+1) {
    	$linha =~ s/(^[0-9]*)//;
		#print " Qtde Nivel: ", $1;
		@filtroSubcadeiaBase[$i] = $1;
		
		$linha =~ s/(^\t)//;
	}
	
}


if ($#ARGV < 2) {
 print "Erro na passagem do parametro\n";
 exit;
}

#$arquivo = $ARGV[0];
open(ARQ_Entrada, "<$ARGV[0]") || die "Arquivo não encontrado\n";

foreach $linha (<ARQ_Entrada>) {	
	&extraiInformacao($linha);
	$estruturaIn = $estruturaBase;
	$qtdeSubcadeiasIn = $qtdeSubcadeiasBase;
	@subcadeiaIn = @subcadeiaBase;
	$qtdePareadosIn = $qtdePareadosBase;
	$qtdeNaoPareadosIn = $qtdeNaoPareadosBase;
	$totalAninhadosIn = $totalAninhadosBase;
	$tamFiltroSubcadeiaIn = $tamFiltroSubcadeiaBase;
	@filtroSubcadeiaIn = @filtroSubcadeiaBase;		
}
close(ARQ_Entrada);

#$arquivo = $ARGV[1];qtde
open(ARQ_BD, "<$ARGV[1]") || die "Arquivo da Base não encontrado\n";
#Arquivo para escrita do que sera buscado pelo Infernal
open(ARQ_BD_Filtrada, ">$ARGV[2]") || die "Arquivo para gerar Base não encontrado\n";

#Arquivo para gravar os descartados
my $Descartada = $ARGV[2];
$Descartada =~ s/Filtrada//;
$Descartada = $Descartada."Descartada"; 
open(ARQ_BD_Descartada, ">$Descartada") || die "Arquivo para gerar Base não encontrado\n";


#Calculando intervalo permitido da qtdeSubcadeias$linha =~ s/(^\t)//;
$intervalo = ($qtdeSubcadeiasIn*$erro);
$LIqtdeSubcadeias = int($qtdeSubcadeiasIn - $intervalo);
$LSqtdeSubcadeias = int($qtdeSubcadeiasIn + $intervalo + 0.5);
print "\nIntervalo: ", $intervalo, " qtdesubcadeia: ", $qtdeSubcadeiasIn, " Multiplicação: ", ($qtdeSubcadeiasIn*$erro);
print "\nqtdeSubcadeiasBase LI: ", $LIqtdeSubcadeias, "  LS: ", $LSqtdeSubcadeias;

$intervalo = ($qtdePareadosIn*$erro);
$LIqtdePareados = int($qtdePareadosIn - $intervalo);
$LSqtdePareados = int($qtdePareadosIn + $intervalo + 0.5);	
print "\nqtdePareadosBase LI: ", $LIqtdePareados, " LS: ", $LSqtdePareados;

$intervalo = ($qtdeNaoPareadosIn*$erro);
$LIqtdeNaoPareado = int($qtdeNaoPareadosIn - $intervalo);
$LSqtdeNaoPareado = int($qtdeNaoPareadosIn + $intervalo + 0.5);	
print "\nqtdeNaoPareadosBase LI: ", $LIqtdeNaoPareado, " LS: ", $LSqtdeNaoPareado;

$intervalo = ($totalAninhadosIn*$erro);
$LItotalAninhados = int($totalAninhadosIn - $intervalo);
$LStotalAninhados = int($totalAninhadosIn + $intervalo + 0.5);	
print "\ntotalAninhadosBase LI: ", $LItotalAninhados, " LS: ", $LStotalAninhados;

foreach $linha (<ARQ_BD>) {
	print "\nLinha: ", $linha;
	
	#Setando flag de semelhança do RNA
	$homologo = 1;
	
	#Descrição
	$linha =~ s/(^>[\w|\s]*\.)//;
	#print "\nDescrição: ", $1;
	$descBase = $1;	
	$linha =~ s/(^\t)//;
	
	#Sequencia
	$linha =~ s/(^[A-Z]*)//;
	#print " Sequencia: ", $1;
	$sequenciaBase = $1;	
	$linha =~ s/(^\t)//;
	
	&extraiInformacao($linha);
	
	#Efetuar comparação entre a entrada e a sequência po nível
	
	if ($tamFiltroSubcadeiaBase > $tamFiltroSubcadeiaIn) { $maxQtdeNivel = $tamFiltroSubcadeiaBase;}
	else { $maxQtdeNivel = $tamFiltroSubcadeiaIn;}
	
	$qtdeForaLimite = 0;
	
	for ($i = 1;$i <= $maxQtdeNivel; $i=$i+1) {
		
		if (($i <= $tamFiltroSubcadeiaBase) && ($i <= $tamFiltroSubcadeiaIn)){

			$intervalo = (@filtroSubcadeiaIn[$i]*$erro);
			$LIfiltroSubcadeia = int(@filtroSubcadeiaIn[$i] - $intervalo);
			$LSfiltroSubcadeia = int(@filtroSubcadeiaIn[$i] + $intervalo + 0.5);
			
			print "\nComparando Entrada: ", int(@filtroSubcadeiaIn[$i]), " e Base: ", int(@filtroSubcadeiaBase[$i]), "!";	
			
			if ((@filtroSubcadeiaBase[$i] < $LIfiltroSubcadeia)||(@filtroSubcadeiaBase[$i] > $LSfiltroSubcadeia)) {
				print "\nFora do Limite na Base", $i, "!";
				$qtdeForaLimite++;				
			}
		}else{
			$qtdeForaLimite++;
		}
				
	}
	
	print "\nQuantidade fora do limite: ", $qtdeForaLimite, "!";
	if ($qtdeForaLimite > $maxForaLimite){
		$homologo = 0;
		print "\nNão é homólogo pelos Níveis. Será feito voto!"
	}
	
	#Se homólogos for igual a 0 será feito a votação
		
	if ($homologo == 0) {
		print "\nEfetuando votos!";
			
		$qtdeVotos = 0;
	
		if (($qtdeSubcadeiasBase < $LIqtdeSubcadeias)||($qtdeSubcadeiasBase > $LSqtdeSubcadeias)) {
			$qtdeVotos++; 
			print "\nNão Passou por Qtde Subcadeia! ";
		}

		if (($qtdePareadosBase < $LIqtdePareados)||($qtdePareadosBase > $LSqtdePareados)) {
			$qtdeVotos++; 
			print "\nNão Passou por Qtde de Pareados! ";
		}
		if (($qtdeNaoPareadosBase < $LIqtdeNaoPareado)||($qtdeNaoPareadosBase > $LSqtdeNaoPareado)) {
			$qtdeVotos++; 
			print "\nNão Passou por Qtde Não Pareados! ";
		}
		if (($totalAninhadosBase < $LItotalAninhados)||($totalAninhadosBase > $LStotalAninhados)) {
			$qtdeVotos++; 
			print "\nNão Passou por Qtde Aninhamentos! ";
		}

	
		# Se obteve maior ou igual que minimo de voltos é descartada
	
		if ($qtdeVotos >= $minimoVotos){
			print "\nQuantidade de Votos: ", $qtdeVotos, ". Descartado!\n";
			print ARQ_BD_Descartada "$descBase\n$sequenciaBase\n$estruturaBase\n";
			
			print ARQ_BD_Descartada "Quantidade por nível: \[Nível,Quantidade]\n";
			for ($i = 1;$i <= $tamFiltroSubcadeiaBase; $i=$i+1) {				
				print ARQ_BD_Descartada "\[$i,@filtroSubcadeiaBase[$i]\] ";		
			}
			
			print ARQ_BD_Descartada "\nEFETUOU VOTAÇÃO!";
			
			print ARQ_BD_Descartada "\nQuantidade de Subcadeias: $qtdeSubcadeiasBase \tIntervalo Esperado: \[$LIqtdeSubcadeias,$LSqtdeSubcadeias\]";
			print ARQ_BD_Descartada "\nQuantidade de Subcadeias: $qtdePareadosBase \tIntervalo Esperado: \[$LIqtdePareados,$LSqtdePareados\]";
			print ARQ_BD_Descartada "\nQuantidade de Subcadeias: $qtdeNaoPareadosBase \tIntervalo Esperado: \[$LIqtdeNaoPareado,$LSqtdeNaoPareado\]";
			print ARQ_BD_Descartada "\nQuantidade de Subcadeias: $totalAninhadosBase \tIntervalo Esperado: \[$LItotalAninhados,$LStotalAninhados\]\n\n";
			
		}else {
			print "\nQuantidade de Votos: ", $qtdeVotos, ". Homólogo!\n";
			print ARQ_BD_Filtrada "$descBase\n$sequenciaBase\n$estruturaBase\n";
			
			print ARQ_BD_Filtrada "Quantidade por nível: \[Nível,Quantidade]\n";
			for ($i = 1;$i <= $tamFiltroSubcadeiaBase; $i=$i+1) {				
				print ARQ_BD_Filtrada "\[$i,@filtroSubcadeiaBase[$i]\] ";		
			}
			print ARQ_BD_Filtrada "\nEFETUOU VOTAÇÃO!";
			print ARQ_BD_Filtrada "\nQuantidade de Subcadeias: $qtdeSubcadeiasBase \tIntervalo Esperado: \[$LIqtdeSubcadeias,$LSqtdeSubcadeias\]";
			print ARQ_BD_Filtrada "\nQuantidade de Subcadeias: $qtdePareadosBase \tIntervalo Esperado: \[$LIqtdePareados,$LSqtdePareados\]";
			print ARQ_BD_Filtrada "\nQuantidade de Subcadeias: $qtdeNaoPareadosBase \tIntervalo Esperado: \[$LIqtdeNaoPareado,$LSqtdeNaoPareado\]";
			print ARQ_BD_Filtrada "\nQuantidade de Subcadeias: $totalAninhadosBase \tIntervalo Esperado: \[$LItotalAninhados,$LStotalAninhados\]\n\n";
			
		}
	}else{
		print ARQ_BD_Filtrada "$descBase\n$sequenciaBase\n$estruturaBase\n";

		print ARQ_BD_Filtrada "Quantidade por nível: \[Nível,Quantidade]\n";
		for ($i = 1;$i <= $tamFiltroSubcadeiaBase; $i=$i+1) {				
			print ARQ_BD_Filtrada "\[$i,@filtroSubcadeiaBase[$i]\] ";		
		}
		
		print ARQ_BD_Filtrada "\nNÃO EFETUOU VOTAÇÃO!";
			
		print ARQ_BD_Filtrada "\nQuantidade de Subcadeias: $qtdeSubcadeiasBase \tIntervalo Esperado: \[$LIqtdeSubcadeias,$LSqtdeSubcadeias\]";
		print ARQ_BD_Filtrada "\nQuantidade de Subcadeias: $qtdePareadosBase \tIntervalo Esperado: \[$LIqtdePareados,$LSqtdePareados\]";
		print ARQ_BD_Filtrada "\nQuantidade de Subcadeias: $qtdeNaoPareadosBase \tIntervalo Esperado: \[$LIqtdeNaoPareado,$LSqtdeNaoPareado\]";
		print ARQ_BD_Filtrada "\nQuantidade de Subcadeias: $totalAninhadosBase \tIntervalo Esperado: \[$LItotalAninhados,$LStotalAninhados\]\n\n";
	}
}

close(ARQ_BD);
close(ARQ_BD_Filtrada);
close(ARQ_BD_Descartada);
    